// ECDH-based encryption utility for API requests
// Adapted from 加密demo.txt, ES module style
import { userApi } from '@/utils/api'
class EcdhCryptoUtil {
  constructor() {
    this.serverPublicKey = null;
    this.clientKeyPair = null;
    this.sharedSecret = null;
    this.sharedBits = null;
    this.clientPublicKeyPEM = null;
  }

  // Initialize ECDH key exchange
  async init() {
    // Fetch server public key (PEM format)
    const response = await userApi.getServerPublicKey()
    const data = await response.json();
    this.serverPublicKey = data.data.publicKey;
  }
  encrypt (data) {
    console.log('data', data)
  }
  // 使用AES-GCM加密数据
  async encryptData(plaintext) {
    try {
        // 派生共享密钥
        const sharedKey = await deriveSharedSecret(serverPublicKey);

        // 生成随机IV
        const iv = window.crypto.getRandomValues(new Uint8Array(12));

        // 调试信息
        console.log("===== 前端加密调试信息 =====");
        console.log("明文长度:", plaintext.length);
        console.log("IV长度:", iv.byteLength);

        // 加密数据
        const encodedPlaintext = new TextEncoder().encode(plaintext);
        const ciphertext = await window.crypto.subtle.encrypt(
          {
            name: "AES-GCM",
            iv: iv
          },
          sharedKey,
          encodedPlaintext
        );

        // 组合IV和密文
        const combinedData = new Uint8Array(iv.length + ciphertext.byteLength);
        combinedData.set(iv);
        combinedData.set(new Uint8Array(ciphertext), iv.length);
        console.log("组合后数据长度:", combinedData.byteLength);

        // 转换为Base64
        return arrayBufferToBase64(combinedData);
    } catch (error) {
        console.error('加密数据错误:', error);
        throw error;
    }
  }

  // 使用ECDH导出共享密钥
  async deriveSharedSecret(serverPublicKey) {
    try {
        const importedServerKey = await importPublicKeyFromPEM(serverPublicKey);
        // 从两个密钥派生比特
        const sharedSecretBits = await window.crypto.subtle.deriveBits(
          {
            name: "ECDH",
            public: importedServerKey
          },
          clientKeyPair.privateKey,
          256 // 32字节用于AES-256
        );
        // 调试输出 - 打印共享密钥的前几个字节（仅开发环境）
        const sharedSecretBytes = new Uint8Array(sharedSecretBits);
        console.log("前端SharedSecret 长度:", sharedSecretBytes.length);
        if (sharedSecretBytes.length > 0) {
          console.log("前端SharedSecret 前4字节:",
          sharedSecretBytes[0].toString(16).padStart(2, '0') +
          sharedSecretBytes[1].toString(16).padStart(2, '0') +
          sharedSecretBytes[2].toString(16).padStart(2, '0') +
          sharedSecretBytes[3].toString(16).padStart(2, '0'));
        }
        // 从共享密钥派生AES-GCM密钥
        return await window.crypto.subtle.importKey(
          "raw",
          sharedSecretBits,
          {
              name: "AES-GCM",
              length: 256
          },
          false,
          ["encrypt", "decrypt"]
        );
    } catch (error) {
      console.error('派生共享密钥错误:', error);
      throw error;
    }
  }

  // 从PEM格式导入服务器公钥
  async importPublicKeyFromPEM(pemString) {
    try {
      // 调试 - 打印PEM字符串头部
      console.log("导入的服务器公钥(部分): ", pemString.substring(0, 50) + "...");
      // 移除PEM头尾并解码Base64
      const base64 = pemString
          .replace('-----BEGIN PUBLIC KEY-----', '')
          .replace('-----END PUBLIC KEY-----', '')
          .replace(/\s+/g, '');
      console.log("移除PEM头尾后长度: ", base64.length);
      const binaryString = window.atob(base64);
      console.log("解码Base64后长度: ", binaryString.length);
      const bytes = new Uint8Array(binaryString.length);
      for (let i = 0; i < binaryString.length; i++) {
        bytes[i] = binaryString.charCodeAt(i);
      }
      // 调试 - 打印前几个字节
      let hexString = "";
      for (let i = 0; i < Math.min(16, bytes.length); i++) {
        hexString += bytes[i].toString(16).padStart(2, '0');
        if (i % 4 == 3) hexString += " ";
      }
      console.log("公钥二进制数据前16字节: ", hexString);
      // 导入密钥
      return await window.crypto.subtle.importKey(
        "spki",
        bytes.buffer,
        {
            name: "ECDH",
            namedCurve: "P-256"
        },
        false,
        []
      );
    } catch (error) {
      console.error('导入公钥错误:', error);
      throw error;
    }
  }

}

export const ecdhCryptoUtil = new EcdhCryptoUtil();
export default EcdhCryptoUtil; 